#pragma once 
#include"log.hpp"
#include<mysql/mysql.h>
#include<string>
#include<jsoncpp/json/json.h>
#include<memory>
#include<sstream>
#include<vector>
#include<fstream>

const std::string Host = "127.0.0.1";
const std::string User = "cls";
const std::string Password = "caolinsong";
const std::string Dbname =  "gobang";
const int Port = 3306;

class mysql_util
{
public:
    static MYSQL* mysql_create(const std::string& host  = Host,const std::string& user = User,const std::string& password =  Password,const std::string& dbname = Dbname
        ,const int port  = Port)
    {
        MYSQL* mysql =  mysql_init(nullptr);
        if(mysql == nullptr)
        {
            ELOG("mysql_init fail");
            return nullptr;
        }
        if(mysql_real_connect(mysql,host.c_str(),user.c_str(),password.c_str(),dbname.c_str(),port,nullptr,0) == nullptr)
        {   
            mysql_destory(mysql);
            ELOG("mysql_real_connect fail:%s",mysql_error(mysql));
            return nullptr;
        }
        if(mysql_set_character_set(mysql,"utf8") != 0)
        {
            mysql_destory(mysql);
            ELOG("mysql_set_character_set fail:%s",mysql_error(mysql));
            return nullptr;
        }
        return mysql;
    }

    static bool mysql_exec(MYSQL* mysql,const std::string& sql)
    {   
        if(mysql_query(mysql,sql.c_str()) != 0)
        {
            mysql_destory(mysql);
            ELOG("mysql_query fail,sql:%s,error:%s",sql.c_str(),mysql_error(mysql));
            return false;
        }
        return true;
    }

    static void mysql_destory(MYSQL* mysql)
    {
        mysql_close(mysql);
    }
};

class json_util
{
public:
    static void serialize(const Json::Value& root,std::string& str)
    {   
        Json::StreamWriterBuilder swb;
        std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
        std::stringstream ss;
        sw->write(root,&ss);
        str =  ss.str();
    }

    static void deserialize(const std::string& str,Json::Value& root)
    {   
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
        std::string  err;
        cr->parse(str.c_str(),str.c_str()+ str.size(),&root,&err);
    }
};

class string_util
{
public:
    static int split(const std::string& str,const std::string& sep,std::vector<std::string>& v)
    {
        size_t index = 0,pos;
        while(index != str.size())
        {
            pos = str.find(sep,index);
            if(pos == std::string::npos)
            {
                v.emplace_back(str.substr(index));
                break;
            } 
            if(index != pos)
            {
                v.emplace_back(str.substr(index,pos - index));
            }
            index = pos + sep.size();
        }
        return v.size();
    }
};

class file_util
{
public:
    static bool read(const std::string& filename,std::string& body)
    {
        std::ifstream input(filename,std::ifstream::binary);
        if(!input.is_open())
        {
            ELOG("open file fail,file name:%s",filename.c_str());
            return false;
        }
        input.seekg(0,std::ifstream::end);
        int filesize = input.tellg();
        input.seekg(0,std::ifstream::beg);
        body.resize(filesize);
        input.read(&body[0],filesize);
        input.close();
        return true;
    }
};